# -*- python -*-
# ex: set syntax=python:

# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This is the buildmaster config file for the 'nacl' bot. It must
# be installed as 'master.cfg' in your buildmaster's base directory
# (although the filename can be changed with the --basedir option to
# 'mktap buildbot master').

# It has one job: define a dictionary named BuildmasterConfig. This
# dictionary has a variety of keys to control different aspects of the
# buildmaster. They are documented in docs/config.xhtml .

# This file follows this naming convention:
# Factories: f_nacl_[dbg/opt/sdk]_[os]
# Builders:  b_nacl_[dbg/opt/sdk]_[os]
# BuildDir:  [dbg/opt/sdk]-[os]
#
# os = linux/mac

from buildbot import locks
from buildbot.scheduler import Scheduler
from buildbot.scheduler import Triggerable

from common import chromium_utils

from master import build_utils
from master import gitiles_poller
from master import master_utils
from master import slaves_list
from master.factory import annotator_factory


import config
import master_site_config

ActiveMaster = master_site_config.NativeClient

nacl_source_url = (
    'https://chromium.googlesource.com/native_client/src/native_client')

# TODO(xusydoc): make Master subclasses handle these overrides automatically.
config.Master.perf_base_url = ActiveMaster.perf_base_url

# gatekeeper-ng is used; see build/scripts/slave/gatekeeper*.json

# This is the dictionary that the buildmaster pays attention to. We also use
# a shorter alias to save typing.
c = BuildmasterConfig = {}

config.DatabaseSetup(c)

master_poller = gitiles_poller.GitilesPoller(nacl_source_url)

c['change_source'] = [master_poller]

def F_NACL_RECIPE():
  return annotator_factory.AnnotatorFactory().BaseFactory(recipe='nacl',
      factory_properties = {'slavetype': 'BuilderTester'});


# BuilderTesters using a custom build configuration.
# The last element of the list is the perf test name (optional) to be
# used by the factory.
#  - If a perf test name is not specified, then the factory must be
#    instantiated inline.
#  - If a perf test name is specified, then the factory is created lazily
#    using the builder_name, and the test name.
factories = [
    # win7-32 (03) -- see bare
    # win7-64 (04)
    ['win7-64-glibc-dbg', '04win7-64', F_NACL_RECIPE()],
    ['win7-64-glibc-opt', '04win7-64', F_NACL_RECIPE()],
    # win8-64 (05)
    ['win8-64-newlib-dbg', '05win8-64', F_NACL_RECIPE()],
    ['win8-64-newlib-opt', '05win8-64', F_NACL_RECIPE()],
    # mac (08)
    ['mac-newlib-dbg', '08mac', F_NACL_RECIPE()],
    ['mac-newlib-opt', '08mac', F_NACL_RECIPE()],
    ['mac-glibc-dbg', '08mac', F_NACL_RECIPE()],
    ['mac-glibc-opt', '08mac', F_NACL_RECIPE()],
    # linux-32 (09)
    ['linux-32-newlib-opt', '09linux-32', F_NACL_RECIPE()],
    ['linux-32-glibc-dbg', '09linux-32', F_NACL_RECIPE()],
    ['linux-32-newlib-dbg', '09linux-32', F_NACL_RECIPE()],
    ['linux-32-glibc-opt', '09linux-32', F_NACL_RECIPE()],
    # linux-64 (10)
    ['linux-64-newlib-opt', '10linux-64', F_NACL_RECIPE()],
    ['linux-64-newlib-opt-test', '10linux-64', F_NACL_RECIPE()],
    ['linux-64-newlib-dbg', '10linux-64', F_NACL_RECIPE()],
    ['linux-64-glibc-opt', '10linux-64', F_NACL_RECIPE()],
    ['linux-64-glibc-dbg', '10linux-64', F_NACL_RECIPE()],
    ['linux-64-validator-opt', '10linux-64', F_NACL_RECIPE()],
    # other (12)
    ['linux-64-newlib-dbg-valgrind', '12other', F_NACL_RECIPE()],
    ['linux-64-glibc-dbg-valgrind', '12other', F_NACL_RECIPE()],
    ['linux_64-newlib-x86_32-spec', '12other', F_NACL_RECIPE()],
    ['linux_64-newlib-x86_64-spec', '12other', F_NACL_RECIPE()],
    ['linux_64-newlib-dbg-asan', '12other', F_NACL_RECIPE()],
    ['mac-newlib-dbg-asan', '12other', F_NACL_RECIPE()],
    # pnacl (13)
    ['linux_64-newlib-x86_32-pnacl', '13pnacl', F_NACL_RECIPE()],
    ['linux_64-newlib-x86_64-pnacl', '13pnacl', F_NACL_RECIPE()],
    ['mac-newlib-opt-pnacl', '13pnacl', F_NACL_RECIPE()],
    ['win7-64-newlib-opt-pnacl', '13pnacl', F_NACL_RECIPE()],
    ['linux_64-newlib-mips-pnacl', '13pnacl', F_NACL_RECIPE()],
    ['linux_64-newlib-x86_32-pnacl-spec', '13pnacl', F_NACL_RECIPE()],
    ['linux_64-newlib-x86_64-pnacl-spec', '13pnacl', F_NACL_RECIPE()],
    # pnaclarm (14)
    ['linux_64-newlib-arm_qemu-pnacl-dbg', '14pnacl-arm', F_NACL_RECIPE()],
    ['linux_64-newlib-arm_qemu-pnacl-opt', '14pnacl-arm', F_NACL_RECIPE()],
    ['oneiric_32-newlib-arm_hw-pnacl-panda-dbg',
     '14pnacl-arm', F_NACL_RECIPE()],
    ['oneiric_32-newlib-arm_hw-pnacl-panda-opt',
     '14pnacl-arm', F_NACL_RECIPE()],
    ['linux_64-newlib-arm_qemu-pnacl-buildonly-spec', '14pnacl-arm|info',
        F_NACL_RECIPE()],
    ['oneiric_32-newlib-arm_hw-pnacl-panda-spec', '14pnacl-arm|info',
        F_NACL_RECIPE()],
    # pnacl-arm (15)
    ['win7-64-arm-newlib-opt', '15arm', F_NACL_RECIPE()],
    ['mac-arm-newlib-opt', '15arm', F_NACL_RECIPE()],
    ['linux-64-arm-newlib-opt', '15arm', F_NACL_RECIPE()],
    ['linux-64-arm-glibc-opt', '15arm', F_NACL_RECIPE()],
    # BARE METAL BOTS (mixed)
    ['win7-32-bare-newlib-opt', '03win7-32', F_NACL_RECIPE()],
    ['win7-32-bare-glibc-opt', '03win7-32', F_NACL_RECIPE()],
    ['win7-64-bare-newlib-opt', '04win7-64', F_NACL_RECIPE()],
    ['win7-64-bare-glibc-opt', '04win7-64', F_NACL_RECIPE()],
    ['linux-32-bare-newlib-opt', '09bare', F_NACL_RECIPE()],
    ['linux-32-bare-glibc-opt', '09bare', F_NACL_RECIPE()],
    ['linux-64-bare-newlib-opt', '09bare', F_NACL_RECIPE()],
    ['linux-64-bare-glibc-opt', '09bare', F_NACL_RECIPE()],
]


####### SCHEDULERS
## configure the Schedulers
# Main scheduler for all changes in trunk.
primary_builders = []
for f in factories:
  if '-arm_hw-' not in f[0]:
    primary_builders.append(f[0])
s_nacl = Scheduler(
   name='nacl',
   branch='master',
   treeStableTimer=60,
   builderNames=primary_builders,
)

s_arm_dbg_hw_tests = Triggerable(
    name='arm_dbg_hw_tests',
    builderNames=['oneiric_32-newlib-arm_hw-pnacl-panda-dbg'])
s_arm_opt_hw_tests = Triggerable(
    name='arm_opt_hw_tests',
    builderNames=['oneiric_32-newlib-arm_hw-pnacl-panda-opt'])
s_arm_spec_hw_tests = Triggerable(
    name='arm_spec_hw_tests',
    builderNames=['oneiric_32-newlib-arm_hw-pnacl-panda-spec'])

c['schedulers'] = [
    s_nacl,
    s_arm_dbg_hw_tests,
    s_arm_opt_hw_tests,
    s_arm_spec_hw_tests,
]


# Setup a per slave lock to prevent more than one thing running at once on
# a single slave.
slave_lock = locks.SlaveLock('overload_lock', maxCount=1)



# ----------------------------------------------------------------------------
# BUILDER DEFINITIONS

# The 'builders' list defines the Builders. Each one is configured with a
# dictionary, using the following keys:
#  name (required): the name used to describe this bilder
#  slavename (required): which slave to use, must appear in c['slaves']
#  builddir (required): which subdirectory to run the builder in
#  factory (required): a BuildFactory to define how the build is run
#  periodicBuildTime (optional): if set, force a build every N seconds
#  category (optional): it is not used in the normal 'buildbot' meaning. It is
#                       used by gatekeeper to determine which steps it should
#                       look for to close the tree.
#

def AutoReboot(builder):
  # Disabling reboot everywhere for now.
  return False


c['builders'] = []
slaves = slaves_list.SlavesList('slaves.cfg', 'NativeClient')
for f in factories:
  c['builders'].append({
      'name': f[0],
      'slavenames': slaves.GetSlavesName(builder=f[0]),
      'builddir': f[0],
      'slavebuilddir': 'nacl',
      'factory': f[2],
      'category': '%s' % f[1],
      'locks': [slave_lock],
      'auto_reboot': AutoReboot(f[0]),
  })


####### BUILDSLAVES

# The 'slaves' list defines the set of allowable buildslaves. List all the
# slaves registered to a builder. Remove dupes.
c['slaves'] = master_utils.AutoSetupSlaves(c['builders'],
                                           config.Master.GetBotPassword())

# Make sure everything works together.
master_utils.VerifySetup(c, slaves)


####### STATUS TARGETS

# Buildbot master url
# Must come before AutoSetupMaster().
c['buildbotURL'] = ActiveMaster.buildbot_url

# Adds common status and tools to this master.
master_utils.AutoSetupMaster(
    c, ActiveMaster,
    public_html='../master.chromium/public_html',
    tagComparator=getattr(c['change_source'][0], 'comparator', None),
    templates=['./templates', '../master.chromium/templates'])


# Adjust the buildCaches to be 3x the number of slaves per builder.
c['autoBuildCacheRatio'] = 3
